-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.


local lu = require 'luaunit'
local unit = require 'unit_manager.class.unit.unit'
local unit_manager = require 'unit_manager.unit_manager'
local npu_board = require 'unit_manager.class.unit.acu.npu_board'
local cmn = require 'common'
local base_messages = require 'messages.base'

TestUnitManager = {}

function TestUnitManager:test_pcbid_to_pcbver()
    -- PcbID合法
    local version = unit.pcbid_to_pcbver(2)
    lu.assertEquals(version, '.B')
    -- PcbID非法
    version = unit.pcbid_to_pcbver(27)
    lu.assertEquals(version, nil)
end

function TestUnitManager:test_logic_version_id_to_version()
    local version = unit.logic_version_id_to_version(1)
    lu.assertEquals(version, '0.01')
end

function TestUnitManager:test_get_device_name()
    unit_manager.device_names = {}
    local name = unit_manager:get_device_name('0101')
    lu.assertEquals(name, nil)
end

function TestUnitManager:test_log_dump_mcu_error_task()
    local ok, skynet = pcall(require, 'skynet')
    if not skynet then
        return 
    end
    skynet.fork = function(cb)
        if ok then
            cb()
        end
    end
    local mds_obj = {
        ['CollectMCULogFlag'] = 0,
        ['Slot'] = 1,
        property_changed = {
        on = function(self,cb) cb('CollectMCULogFlag', 1) end
        }
    }
    local obj = {
        get_prop=function (self,name) 
            if not self.mds_obj then
                return nil
            elseif self.mds_obj[name] then
                return self.mds_obj[name]
            end
        end,
        update_dump_log=function (self,cb) 
            return cb
        end
    }
    obj.mds_obj=mds_obj
    unit_manager.npu_boards = {}
    table.insert(unit_manager.npu_boards, obj)
    unit_manager.npu_need_collect_count_table = {}
    unit_manager.npu_collecting_count_table = {}
    unit_manager.npu_collecting_count = 0
    unit_manager:log_dump_mcu_error_task()
    unit_manager.npu_collecting_count_table = {[mds_obj['Slot']]=1}
    unit_manager:monitor_collect_mcu_log_flag(obj)
    unit_manager:monitor_need_collect_mcu()
    lu.assertEquals( unit_manager.npu_need_collect_count_table[1], 1)
end

local client = require 'general_hardware.client'
local c_logic_fw = require 'unit_manager.class.logic_fw.fw_init'

function TestUnitManager:test_unregister_cpld_firmware_info()
    local old_func = {}
    old_func.FirmwareInventoryDelete = client.PFirmwareInventoryFirmwareInventoryDelete

    unit_manager.logic_fw = {{position=1, id=1}}
    -- 删除执行成功
    client.PFirmwareInventoryFirmwareInventoryDelete = function(...)
        return true
    end
    unit_manager:unregister_cpld_firmware_info(1)
    lu.assertEquals(unit_manager.logic_fw[1].id, nil)

    -- 删除执行失败
    unit_manager.logic_fw[1].id = 2
    client.PFirmwareInventoryFirmwareInventoryDelete = function(...)
        return false
    end
    unit_manager:unregister_cpld_firmware_info(1)
    lu.assertEquals(unit_manager.logic_fw[1].id, 2)

    client.PFirmwareInventoryFirmwareInventoryDelete = old_func.FirmwareInventoryDelete
end

function TestUnitManager:test_post_reset()
    local REGION_PROP<const> = {
        [0x0] = {
            'GlobalReset', 'GlobalResetLocked', 'Global'
        },
        [0x1] = {
            'ComputingUnitReset', 'ComputingUnitResetLocked', 'ComputingUnit'
        }
    }
    local ok = unit_manager:post_reset({
        set_prop = function()
            return true
        end
    }, REGION_PROP)
    lu.assertEquals(ok, true)

    ok = unit_manager:post_reset({
        set_prop = function()
            error('set fail')
        end
    }, REGION_PROP)
    lu.assertEquals(ok, false)
end

local function construct_ctx()
    local ctx = {}
    ctx.ChanType = 1
    ctx.get_initiator = function()
        return {}
    end

    return ctx
end

function TestUnitManager:test_reset_npu_region()
    local npu_board = {
        set_prop = function()
            return true
        end
    }
    local ok, res = pcall(function()
        unit_manager:reset_npu_region(npu_board, construct_ctx(), 0xff)
    end)
    lu.assertEquals(ok, false)
    lu.assertEquals(res.name, base_messages.PropertyValueNotInListMessage.Name)

    npu_board = {
        set_prop = function()
            error('set fail')
        end
    }
    ok, res = pcall(function()
        unit_manager:reset_npu_region(npu_board, construct_ctx(), 0x0)
    end)
    lu.assertEquals(ok, false)
    lu.assertEquals(res.name, base_messages.InternalErrorMessage.Name)

    npu_board = {
        set_prop = function()
            return true
        end
    }
    ok = pcall(function()
        unit_manager:reset_npu_region(npu_board, construct_ctx(), 0x0)
    end)
    lu.assertEquals(ok, true)

    ok = pcall(function()
        unit_manager:reset_npu_region(npu_board, construct_ctx(), 0x1)
    end)
    lu.assertEquals(ok, true)
end

function TestUnitManager:test_reset_npu_device()
    unit_manager.npu_board_map = {
        ['npu'] = {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 1
            end
        }
    }

    local ok = unit_manager:reset_npu_device({
        path = 'npu1'
    })
    lu.assertEquals(ok, false)

    unit_manager.npu_board_map = {
        ['npu'] = {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 2
            end
        }
    }
    ok = unit_manager:reset_npu_device({
        path = 'npu'
    }, construct_ctx(), 0x01)
    lu.assertEquals(ok, nil)

    unit_manager.npu_board_map = {
        ['npu'] = {
            set_prop = function()
                return true
            end,
            get_prop = function()
                return 1
            end
        }
    }
    ok = unit_manager:reset_npu_device({
        path = 'npu'
    }, construct_ctx(), 0x01)
    lu.assertEquals(ok, nil)
    self:get_npu_metric_collection_data()
    self:get_npu_metric_collection_items()
end

function TestUnitManager:get_npu_metric_collection_data()
    local unit = unit_manager.get_instance()
    unit.npu_board_map = {}
    local res = unit:get_npu_metric_collection_data({})
    lu.assertEquals(#res, 0)

    unit.npu_board_map = {
        ['npu'] = {}
    }
    res = unit:get_npu_metric_collection_data({
        path = 'npu'
    }, {})
    lu.assertEquals(#res, 0)

    res = unit:get_npu_metric_collection_data({
        path = 'npu'
    }, {
        [1] = 'npuboard.power'
    })
    lu.assertEquals(#res, 0)

    unit.npu_board_map = {
        ['npu'] = {
            get_prop = function()
                return 32768
            end
        }
    }
    res = unit:get_npu_metric_collection_data({
        path = 'npu'
    }, {
        [1] = 'npuboard.powerwatts'
    })
    lu.assertEquals(#res, 0)

    unit.npu_board_map = {
        ['npu'] = {
            get_prop = function()
                return 66
            end
        }
    }
    res = unit:get_npu_metric_collection_data({
        path = 'npu'
    }, {
        [1] = 'npuboard.powerwatts'
    })
    lu.assertEquals(#res, 1)
end

function TestUnitManager:get_npu_metric_collection_items()
    local unit = unit_manager.get_instance()
    unit.npu_board_map = {}
    local res = unit:get_npu_metric_collection_items({})
    lu.assertEquals(res, '')

    unit.npu_board_map = {
        ['npu'] = {
            get_prop = function()
                return 66
            end
        }
    }

    local res = unit:get_npu_metric_collection_items({
        path = 'npu'
    })
    lu.assertEquals(res, 'NpuBoard')
end